#ifndef TC_ATR_HPP
#define TC_ATR_HPP

/** \file ATR.hpp
 * Definition of the ATR function template.
 *
 * (C) Copyright by Semih Cemiloglu
 * All rights reserved, see COPYRIGHT file for details.
 *
 * $Id: ATR.hpp 110 2006-06-19 03:38:33Z semihc $
 *
 *
 */


#include "TA.hh"
#include "DBC.hpp"
#include "CircArray.hpp"


namespace TC {

  //! Average True Range Calculator
  TC_EXPORT template <typename InputIterator,
                      typename OutputIterator,
                      class Adaptor>
  void ATR(InputIterator fromPos,
           InputIterator fromEnd,
           OutputIterator toPos,
           const unsigned period,
           const Adaptor adaptor)
  {
    TC_PRE_CONDITION(period > 0);


    // True range
    register TAfp_t tr; 
    // Yesterday's close
    register TAfp_t ycls = adaptor.cls(*fromPos);
    // Today's high
    register TAfp_t thi; 
    // Today's low
    register TAfp_t tlo;
    // Temporary range calculation
    TAfp_t range[3];
    CircArray<TAfp_t> tr_arr(period);


    for(; fromPos!=fromEnd; ++fromPos) {
      // Get high and low values
      thi = adaptor.hi(*fromPos);
      tlo = adaptor.lo(*fromPos);
      // Calculate ranges
      if(thi > tlo) 
        range[0] = thi - tlo;
      else 
        range[0] = tlo - thi;
      if(ycls > thi)
        range[1] = ycls - thi;
      else
        range[1] = thi - ycls;
      if(ycls > tlo)
        range[2] = ycls - tlo;
      else
        range[2] = tlo - ycls;
      // Store the today's close as yesterday's
      ycls = adaptor.cls(*fromPos);
      // Find the true (greatest) range
      tr = range[0];
      if(range[1] > tr)
        tr = range[1];
      if(range[2] > tr)
        tr = range[2];
      
      // Store the true range in circular array
      tr_arr.push(tr);
      
      // Output the average true range
      *toPos = tr_arr.avg();
      ++toPos;

    } // end for

  }

} // end namespace


#endif /* Include guard */
